﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.Compilation;
using System.Web.Configuration;
using System.Web.Hosting;
using Vision.Cms.Common.ClientBuild;
using Vision.Utilities.ConsoleApp.PreCompilation;

namespace Vision.Utilities.ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {

            //var buildProviderTypeName = "System.Web.Compilation.PageBuildProvider";
            //var type1= typeof(BuildManager).Assembly.GetType(buildProviderTypeName);

            Console.WriteLine("Input 0 to start:");
            var key = Console.Read();
            if (key == 48)
            {
                var appPhysicalSourceDir = ConfigurationHelper.GetWebAppSetting<string>("appPhysicalSourceDir");
                var appPhysicalTargetDir = ConfigurationHelper.GetWebAppSetting<string>("appPhysicalTargetDir");
                PreCompile(appPhysicalSourceDir, appPhysicalTargetDir);
            }
            Console.WriteLine("Finished...");
            Console.ReadKey();
        }


        private static void PreCompile(string appPhysicalSourceDir, string appPhysicalTargetDir)
        {
            if (Directory.Exists(appPhysicalTargetDir))
                Directory.Delete(appPhysicalTargetDir, true);

            var appVirtualDir = "/";
            var parameters = new ClientBuildManagerParameter();
            parameters.ExcludedVirtualPaths.Add("/global.asax");
           // parameters.PrecompilationFlags = PrecompilationFlags.Default | PrecompilationFlags.Updatable;
            //parameters.PrecompilationFlags = PrecompilationFlags.Clean;
            var clientBuildManager = new ClientBuildManager(appVirtualDir, appPhysicalSourceDir, appPhysicalTargetDir, parameters);

            try
            {
                var clientBuildCallback = new CmsClientBuildManagerCallback();
                clientBuildManager.AppDomainStarted += clientBuildManager_AppDomainStarted;
                clientBuildManager.PrecompileApplication(clientBuildCallback);

                //var fileVirtualDir = "/Admin/Components/BusinessDirectory/Views/Business/Shared/BusinessDetailsEdit.ascx";
                //fileVirtualDir = "/Areas/BuiltIn/Views/Sso/Index.aspx";
                ////clientBuildManager.CompileFile(fileVirtualDir, clientBuildCallback);
                
                clientBuildUtility.Callback(appPhysicalSourceDir, appPhysicalTargetDir);
            }
            catch (Exception e)
            {
                throw;
            }
        }

        static readonly ConcurrentDictionary<string, Assembly> Assemblies = new ConcurrentDictionary<string, Assembly>();
        static IClientBuildUtility clientBuildUtility;
             
        static void clientBuildManager_AppDomainStarted(object sender, EventArgs e)
        {
            var clientBuildManager = sender as ClientBuildManager;
            if (clientBuildManager.IsHostCreated)
            {
                var buildManagerHostFieldInfo = typeof(ClientBuildManager).GetField("_host", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
                var buildManagerHost = buildManagerHostFieldInfo.GetValue(clientBuildManager);

                var appHostFieldInfo = typeof(ClientBuildManager).GetField("_appHost", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
                var appHost = appHostFieldInfo.GetValue(clientBuildManager) as IApplicationHost;
                //var appDomain = ApplicationManager.GetApplicationManager().GetAppDomain(appHost);

                var applicationManager = ApplicationManager.GetApplicationManager();
                var runningApplications = applicationManager.GetRunningApplications();
                var applicationInfo = runningApplications.FirstOrDefault(c => c.PhysicalPath.Equals(GetPhysicalPath(clientBuildManager), StringComparison.InvariantCultureIgnoreCase));

                var appDomain = applicationManager.GetAppDomain(applicationInfo.ID);

                clientBuildUtility = appDomain.CreateInstanceAndUnwrap("Vision.Cms.Mvc", "Vision.Cms.Mvc.Infrastructure.ClientBuild.ClientBuildUtility") as IClientBuildUtility;

                // This is the most important thing, we need use the Web Site AppDomain object to do something to initialize.
                clientBuildUtility.Initialize();
                //var registerType = clientBuildUtility.GetVirtualPathProviderType();

                //var virtualPath = "/Admin/Components/BusinessDirectory/App_Data/EmailTemplates/ConfirmBusinessSubmissionEmailTemplate.xslt";
                //var hostMapped = clientBuildUtility.MapPath(virtualPath);

                //var siteMapped = clientBuildUtility.SiteMapPath(virtualPath);

                //virtualPath = "/Areas/BuiltIn/Views/Sso/Index.aspx";
                //hostMapped = clientBuildUtility.MapPath(virtualPath);

                //siteMapped = clientBuildUtility.SiteMapPath(virtualPath);

                //var ddd = siteMapped.Length;
                //var RegisterMethodInfo = clientBuildUtility.GetType().GetMethod("Register", BindingFlags.Instance | BindingFlags.Public);
                //RegisterMethodInfo.Invoke(clientBuildUtility,null);

                //var GetVirtualPathProviderTypeMethodInfo = clientBuildUtility.GetType().GetMethod("GetVirtualPathProviderType", BindingFlags.Instance | BindingFlags.Public);
                //var providerType = GetVirtualPathProviderTypeMethodInfo.Invoke(clientBuildUtility, null);

                AppDomainSetup dd;
               
                //var hostingParametersFieldInfo = typeof(ClientBuildManager).GetField("_hostingParameters", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
                //var hostingParameters = hostingParametersFieldInfo.GetValue(clientBuildManager);

                //var GetAppDomainWithHostingEnvironmentMethodInfo = typeof(ApplicationManager).GetMethod("GetAppDomainWithHostingEnvironment", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
                //var hostingEnvironment = GetAppDomainWithHostingEnvironmentMethodInfo.Invoke(applicationManager, new object[] { applicationInfo.ID, appHost, hostingParameters }) as HostingEnvironment;


                //var virtualPathProviderFieldInfo = hostingEnvironment.GetType().GetField("_virtualPathProvider", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
                //var virtualPathProvider = virtualPathProviderFieldInfo.GetValue(hostingEnvironment);

                //var registerAssemblyMethodInfo = buildManagerHost.GetType().GetMethod("RegisterAssembly", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
                //var dllFiles = Directory.GetFiles(@"D:\Site Packages\CMS6\CMS6\bin\", "*.dll");
                //foreach (var dllFile in dllFiles)
                //{
                //    try
                //    {
                //        var assembly = Assembly.LoadFile(dllFile);
                //        //registerAssemblyMethodInfo.Invoke(buildManagerHost, new object[] { assembly.FullName, dllFile });
                //        Assemblies.TryAdd(assembly.FullName, assembly);
                //    }
                //    catch { }
                //}

                //var assemlbyCollectionFieldInfo = buildManagerHost.GetType().GetField("_assemblyCollection", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
                //var assemlbyCollection = assemlbyCollectionFieldInfo.GetValue(buildManagerHost);
                //var buildManagerFieldInfo = buildManagerHost.GetType().GetField("_buildManager", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
                //var buildManager = buildManagerFieldInfo.GetValue(buildManagerHost);

                //WebConfigurationFileMap fileMap = new WebConfigurationFileMap();
                //VirtualPath path = VirtualPath.Create(virtualPath);
                //fileMap.VirtualDirectories.Add(path.VirtualPathStringNoTrailingSlash, new VirtualDirectoryMapping(physicalPath, true));
                //fileMap.VirtualDirectories.Add(HttpRuntime.AspClientScriptVirtualPath, new VirtualDirectoryMapping(HttpRuntime.AspClientScriptPhysicalPathInternal, false));
                //return new UserMapPath(fileMap);

            }
            
            // Register virtual Path Provider
            //var virtualPathProvider = new CmsVirtualPathProvider();
            //HostingEnvironment.RegisterVirtualPathProvider(virtualPathProvider);

            // Register ReferencedAssembly.
            //BuildManager.AddReferencedAssembly();
        }

        static Assembly appDomain_TypeResolve(object sender, ResolveEventArgs args)
        {
            return null;
        }

        static Assembly appDomain_AssemblyResolve(object sender, ResolveEventArgs args)
        {
            return null;             
        }

        static string GetPhysicalPath(ClientBuildManager clientBuildManager)
        {
            var physicalPathFieldInfo = typeof(ClientBuildManager).GetField("_physicalPath", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
            return (string)physicalPathFieldInfo.GetValue(clientBuildManager);
        }

    }
}
